#include <cppunit/config/SourcePrefix.h>
#include <iostream>
#include "SystemTest.h"
#include <iterator>


void SystemTest::setUp()
{}

void SystemTest::tearDown()
{}

CPPUNIT_TEST_SUITE_REGISTRATION( SystemTest ); 


void SystemTest::testSystem() {
	
	FrontEndController controller = FrontEndController();
	cout << "Testing first source..\n";
	checkQueries("Source1.txt", "SQueries1.txt", controller);

	//cout << "Testing second source..\n";
	//controller = FrontEndController();
	//checkQueries("Source2.txt", "SQueries2.txt", controller);
	
	return;
}

void SystemTest::checkQueries(string sourcename, string queryname, FrontEndController controller) {
	
	// Initialize variables
	string line = "";
	string query = "";
	vector<string> results;
	vector<string> tokens;
	int numQueries;
	string expected;
	ifstream queryFile;

	// Confirm source and query file names
	cout << "Source file name: " << sourcename << "\nQuery file name: " << queryname << "\n";
	
	// Parse source
	controller.frontEndParse(sourcename);
	
	// Extract required lines from query file
	queryFile.open(queryname);
	getline(queryFile, line);
	numQueries = atoi(line.c_str());
	getline(queryFile, line);
	
	// Compary outputs for each query
	for (int i = 0; i < numQueries; i++) {
		
		// Remove description line
		getline(queryFile, line);

		// Get design-entity definition line
		getline(queryFile, line);
		query.append(line);
		query.append(" ");

		// Get actual query
		getline(queryFile, line);
		query.append(line);

		// Get results of query
		results = controller.frontEndEvaluate(query);
		
		// Get expected line
		getline(queryFile, line);

		istringstream iss(line);
		copy(istream_iterator<string>(iss),
         istream_iterator<string>(),
		 back_inserter<vector<string>>(tokens));
		
		// Sort and compare results
		std::sort(results.begin(), results.end());
		std::sort(tokens.begin(), tokens.end());
		list<string> matches;

		set_intersection(results.begin(), results.end(),
                 tokens.begin(), tokens.end(),
                 back_inserter(matches));

		// Display result of test
		if (matches.size() == tokens.size()) {
				CPPUNIT_ASSERT(true);
				cout << "Test case success!\n";
		}
		else {
			cout << "Test case failed.\n";
			CPPUNIT_ASSERT(false);
		}
	}

	return;
}